//
//  ZCBaseRequestManager.m
//  UniversalApp
//
//  Created by 凯朱 on 2019/6/11.
//  Copyright © 2019 徐阳. All rights reserved.
//

#import "ZCBaseRequestManager.h"
#import "YQNetworking.h"
#import "Reachability.h"
#import <CommonCrypto/CommonCrypto.h>
static  NSString *const kRequestFaildMessage = @"网络请求失败，请稍后重试";
static  NSString *const kWithoutNetworkMessage = @"客户端无有效的网络连接";

@interface ZCBaseRequestManager()

@end


@implementation ZCBaseRequestManager
/*
 发起网络请求
 
 @param url url
 @param method 请求方式
 @param params 参数
 @param finished 完成回调
 */
+(void)requestWithUrl:(NSString *)url method:(ZCRequestMethod)method params:(NSDictionary *)params finished:(ZCRequiredFinished)finished{
    NSDictionary *paramsNew = [self configParams:params];
    [YQNetworking setupTimeout:20];
    if (method == GET) {
        [YQNetworking getWithUrl:url refreshRequest:NO cache:NO jsonRequest:YES params:paramsNew progressBlock:nil successBlock:^(id response) {
            [self handleResultWithResponse:response error:nil finished:finished];
        } failBlock:^(NSError *error) {
            [self handleResultWithResponse:nil error:error finished:finished];
        }];
    }else{
        [YQNetworking postWithUrl:url refreshRequest:NO cache:NO jsonRequest:YES params:paramsNew progressBlock:nil successBlock:^(id response) {
            [self handleResultWithResponse:response error:nil finished:finished];
        } failBlock:^(NSError *error) {
            [self handleResultWithResponse:nil error:error finished:finished];
        }];
    }
}

+(NSDictionary *)configParams:(NSDictionary *)params{
    NSMutableDictionary *newParams = [[NSMutableDictionary alloc] initWithDictionary:params];
    
    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
//    NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
    NSString *bundleId = @"com.geniecredit.loanios";
    NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
    NSString *phoneModel = [UIDevice currentDevice].machineModelName;
    NSString *sysVer = [UIDevice currentDevice].systemVersion;
    NSString *time = [[NSDate date] timestampMinSec];
    NSString *md5Key = @"";
    NSString *appsFlyerId = @"";
    NSString *platform = @"ios";
    NSString *signStr = [NSString stringWithFormat:@"%@%@%@%@%@%@%@",time,md5Key,kToken,appsFlyerId,bundleId,app_Version,platform];
    NSString *sign = [signStr md5String];
    NSDictionary *baseInfo = @{@"platform":platform,
                               @"bundleId":bundleId,
                               @"app_package_name":@"",
                               @"app_version":app_Version,
                               @"version":app_Version,
                               @"register_type":@"ios",
                               @"device_name":phoneModel,
                               @"device":@"ios",
                               @"device_version":sysVer,
                               @"device_sn":@"",
                               @"app_name":@"SJPay",
                               @"channle":@"",
                               @"token":kToken,
                               @"appsFlyerId":appsFlyerId,
                               @"timestamp":time,
                               @"sign":sign};
    
    [newParams addEntriesFromDictionary:baseInfo];
    NSString *jsonStr = [ZCTool objectToJson:newParams];
    NSString *key = [NSString dateStrFromDate:[NSDate date] formatStr:@"yyyyMMyyyyMMyyyy"];
    NSString *dataStr = [self encrypt:jsonStr withKey:key];
    NSDictionary *finalParams = @{@"data":dataStr};
    
    NSDictionary *header = @{@"appsFlyerId":@"",
                             @"version":app_Version,
                             @"timestamp":[[NSDate date] timestampMinSec],
                             @"sign":sign,
                             @"platform":@"IOS",
                             @"visit_source":@"IOS"};
    NSLog(@"请求参数 %@",newParams);
    NSLog(@"signStr = %@",signStr);
    [YQNetworking configHttpHeader:header];
    
    return finalParams;
}

+ (NSString *)encrypt:(NSString *)plainText withKey:(NSString *)key {
    // 将密钥转换为 NSData
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    
    // 将明文字符串转换为 NSData
    NSData *data = [plainText dataUsingEncoding:NSUTF8StringEncoding];

    // 创建加密上下文
    CCCryptorRef cryptor = NULL;
    CCCryptorStatus status = CCCryptorCreate(kCCEncrypt,
                                             kCCAlgorithmAES,
                                             kCCOptionPKCS7Padding|kCCOptionECBMode,
                                             keyData.bytes,
                                             keyData.length,
                                             NULL, // IV 不适用 ECB 模式
                                             &cryptor);
    
    if (status != kCCSuccess) {
        NSLog(@"Error creating encryptor: %d", status);
        return nil;
    }

    size_t bufferLength = data.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferLength);
    
    size_t encryptedLength = 0;
    status = CCCryptorUpdate(cryptor,
                             data.bytes,
                             data.length,
                             buffer,
                             bufferLength,
                             &encryptedLength);
    
    if (status != kCCSuccess) {
        NSLog(@"Error during encryption update: %d", status);
        free(buffer);
        CCCryptorRelease(cryptor);
        return nil;
    }

    size_t finalLength = 0;
    status = CCCryptorFinal(cryptor,
                            (void *)((char *)buffer + encryptedLength),
                            bufferLength - encryptedLength,
                            &finalLength);

    if (status != kCCSuccess) {
        NSLog(@"Error during encryption finalization: %d", status);
        free(buffer);
        CCCryptorRelease(cryptor);
        return nil;
    }

    encryptedLength += finalLength;
    NSData *encryptedData = [NSData dataWithBytesNoCopy:buffer length:encryptedLength];

    // 将加密后的 NSData 转换为 Base64 字符串
    NSString *base64String = [encryptedData base64EncodedStringWithOptions:0];

    return base64String;
}

+ (NSString *)decrypt:(NSString *)encryptedString withKey:(NSString *)key {
    // 将密钥转换为 NSData
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];

    // 将 Base64 编码的加密字符串转换为 NSData
    NSData *data = [[NSData alloc] initWithBase64EncodedString:encryptedString options:0];

    // 创建解密上下文
    CCCryptorRef cryptor = NULL;
    CCCryptorStatus status = CCCryptorCreate(kCCDecrypt,
                                             kCCAlgorithmAES,
                                             kCCOptionPKCS7Padding|kCCOptionECBMode,
                                             keyData.bytes,
                                             keyData.length,
                                             NULL, // IV 不需要
                                             &cryptor);

    if (status != kCCSuccess) {
        NSLog(@"Error creating decryptor: %d", status);
        return nil;
    }

    size_t bufferLength = data.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferLength);

    size_t decryptedLength = 0;
    status = CCCryptorUpdate(cryptor,
                             data.bytes,
                             data.length,
                             buffer,
                             bufferLength,
                             &decryptedLength);

    if (status != kCCSuccess) {
        NSLog(@"Error during decryption update: %d", status);
        free(buffer);
        CCCryptorRelease(cryptor);
        return nil;
    }

    size_t finalLength = 0;
    status = CCCryptorFinal(cryptor,
                            (void *)((char *)buffer + decryptedLength),
                            bufferLength - decryptedLength,
                            &finalLength);

    if (status != kCCSuccess) {
        NSLog(@"Error during decryption finalization: %d", status);
        free(buffer);
        CCCryptorRelease(cryptor);
        return nil;
    }

    decryptedLength += finalLength;
    NSData *decryptedData = [NSData dataWithBytesNoCopy:buffer length:decryptedLength];

    // 将 NSData 转换为 NSString
    NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];

    return decryptedString;
}


/*
 发起网络请求json请求
 
 @param url url
 @param method 请求方式
 @param params 参数
 @param finished 完成回调
 */
+(void)requestJsonWithUrl:(NSString *)url method:(ZCRequestMethod)method params:(NSDictionary *)params finished:(ZCRequiredFinished)finished{
    [YQNetworking configHttpHeader:@{@"token":kToken}];
    [YQNetworking setupTimeout:20];
  
    if (method == GET) {
        [YQNetworking getWithUrl:url refreshRequest:NO cache:NO jsonRequest:YES params:params progressBlock:nil successBlock:^(id response) {
            [self handleResultWithResponse:response error:nil finished:finished];
        } failBlock:^(NSError *error) {
            [self handleResultWithResponse:nil error:error finished:finished];
        }];
    }else{
        [YQNetworking postWithUrl:url refreshRequest:NO cache:NO jsonRequest:YES params:params progressBlock:nil successBlock:^(id response) {
            [self handleResultWithResponse:response error:nil finished:finished];
        } failBlock:^(NSError *error) {
            [self handleResultWithResponse:nil error:error finished:finished];
        }];
    }
}


#pragma mark - ————— 图片上传 <表单专用> —————

/**
 处理网络请求结果
 
 @param response 响应体
 @param error 错误
 */
+(void)handleResultWithResponse:(id)response error:(NSError *)error
                       finished:(ZCRequiredFinished)finished{
    
    //请求错误
    if (error) {
        NSString *message = [self getNetworkErrorMessageWith:error.code];
        if (finished) finished(NO,@"",@"",message);
        return;
    }
    
    NSString *dataStr = response[@"data"];
    //解密
    NSString *key = [NSString dateStrFromDate:[NSDate date] formatStr:@"yyyyMMyyyyMMyyyy"];
    NSString *jsonStr = [self decrypt:dataStr withKey:key];
    NSDictionary *data = [ZCTool dictionaryWithJsonStr:jsonStr];
    NSString *code = kSTRING(data[@"code"]);
    NSString *message = kSTRING(data[@"msg"]);
    
    if ([code isEqualToString:@"403100"] || [code isEqualToString:@"403100"] || [code isEqualToString:@"501"]) {
        [[UserManager sharedUserManager] removeUserData];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"loginStatusChange" object:nil];
        kShowToast(@"登录过期");
        return;
    }
    
    if ([code isEqualToString:@"200"]) {
        if (finished) finished(YES,data,code,message);
    }
    else{
        if (finished) finished(NO,data,code,message);
    }
}


/*
 解析错误码
 
 @param code 返回提示
 */
+(NSString *)getNetworkErrorMessageWith:(NSInteger)code{
    NSString *errorMesg = kRequestFaildMessage;
    if(![self checkNetWork])//没有网络
    {
        return kWithoutNetworkMessage;
    }
    
    switch (code) {
        case -1001://NSURLErrorTimedOut
            errorMesg = @"网络请求超时";
            break;
        case -1005://NSURLErrorNetworkConnectionLost
            errorMesg = @"网络连接异常";
            break;
        case -1011://NSURLErrorBadServerResponse
            errorMesg = @"服务忙，请稍后再试";
            break;
        case -999://请求被取消了不提示
            errorMesg = @"";
            break;
    }
    return errorMesg;
}

#pragma mark -
#pragma mark - ================<网络、其他校验>===============
/**
 网络检查
 
 @return YES-有网络 NO-无网络
 */
+(BOOL)checkNetWork{
    
    BOOL isHaveNet = YES;
    Reachability *r = [Reachability reachabilityWithHostName:URL_main];
    switch ([r currentReachabilityStatus]) {
        case NotReachable:{
            isHaveNet = NO;
            break;
        }
        case ReachableViaWiFi: case ReachableViaWWAN:{
            isHaveNet = YES;
            break;
        }
        default:{
            break;
        }
    }
    return isHaveNet;
}

@end
